[XEND] Proper support for devices with UUID. Removing old workaround
authorAlastair Tse <atse@xensource.com>
Fri, 6 Oct 2006 15:27:06 +0000 (16:27 +0100)
committerAlastair Tse <atse@xensource.com>
Fri, 6 Oct 2006 15:27:06 +0000 (16:27 +0100)
with augmented VM UUIDs with devids.

Signed-off-by: Alastair Tse <atse@xensource.com>
tools/python/xen/xend/XendAPI.py
tools/python/xen/xend/XendConfig.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/DevController.py

index 402e0bcbceb776fe71ed6a73b4b397c8228b9434..e91ee95e1147433b84186261b871bdd653edb9db 100644 (file)
@@ -948,9 +948,14 @@ class XendAPI:
     # object methods
     def vbd_get_record(self, session, vbd_ref):
         xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_by_uuid('vbd', vbd_ref,
-                                                      'driver'))
-
+        vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
+        if not vm:
+            return xen_api_error(XEND_ERROR_VIF_INVALID)
+        cfg = vm.get_dev_xenapi_config('vbd', vbd_ref)
+        if not cfg:
+            return xen_api_error(XEND_ERROR_UNKNOWN)
+        return xen_api_success(cfg)
+    
     # class methods
     def vbd_create(self, session, vbd_struct):
         xendom = XendDomain.instance()
@@ -968,20 +973,20 @@ class XendAPI:
     # attributes (rw)
     def vbd_get_vm(self, session, vbd_ref):
         xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_by_uuid('vbd', vbd_ref, 'VM'))
+        return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'VM'))
     def vbd_get_vdi(self, session, vbd_ref):
         return xen_api_error(XEND_ERROR_UNSUPPORTED)
     def vbd_get_device(self, session, vbd_ref):
         xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_by_uuid('vbd', vbd_ref,
+        return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
                                                       'device'))
     def vbd_get_mode(self, session, vbd_ref):
         xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_by_uuid('vbd', vbd_ref,
+        return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
                                                       'mode'))
     def vbd_get_driver(self, session, vbd_ref):
         xendom = XendDomain.instance()
-        return xen_api_success(xendom.get_dev_by_uuid('vbd', vbd_ref,
+        return xen_api_success(xendom.get_dev_property('vbd', vbd_ref,
                                                       'driver'))
 
     # Xen API: Class VIF
@@ -1001,6 +1006,23 @@ class XendAPI:
 
     VIF_attr_inst = VIF_attr_rw
 
+    # object methods
+    def vif_get_record(self, session, vif_ref):
+        xendom = XendDomain.instance()
+        vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
+        if not vm:
+            return xen_api_error(XEND_ERROR_VIF_INVALID)
+        cfg = vm.get_dev_xenapi_config('vif', vif_ref)
+        if not cfg:
+            return xen_api_error(XEND_ERROR_UNKNOWN)
+        valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \
+                         self.Base_attr_ro + self.Base_attr_rw
+        for k in cfg.keys():
+            if k not in valid_vif_keys:
+                del cfg[k]
+            
+        return xen_api_success(cfg)
+
     # class methods
     def vif_create(self, session, vif_struct):
         xendom = XendDomain.instance()
index ba6337b0c5c9527dea804199c0f852111e4e6efc..8fbf9cbb23b687b1ac4f81095ba62424510075df 100644 (file)
@@ -717,6 +717,12 @@ class XendConfig(dict):
                 raise XendConfigError('Invalid restart event: %s = %s' % \
                                       (event, str(self[event])))
 
+        # Verify that {vif,vbd}_refs are here too
+        if 'vif_refs' not in self:
+            self['vif_refs'] = []
+        if 'vbd_refs' not in self:
+            self['vbd_refs'] = []
+
     def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None):
         if dev_type not in XendDevices.valid_devices():
             raise XendConfigError("XendConfig: %s not a valid device type" %
index 604c298db5b143caa560a8f0ea72cc9456b1e485..dee31a331b2174f87a92be46423f75d0b1624cf9 100644 (file)
@@ -563,22 +563,25 @@ class XendDomain:
         finally:
             self.domains_lock.release()
 
-    def get_dev_by_uuid(self, klass, dev_uuid, field):
-        parts = dev_uuid.split('-%s-' % klass, 1)
+    def get_vm_with_dev_uuid(self, klass, dev_uuid):
+        self.domains_lock.acquire()
         try:
-            if len(parts) > 1:
-                dom = self.get_vm_by_uuid(parts[0])
-                if not dom:
-                    return None
-                
-                if field == 'VM':
-                    return dom.get_uuid()
-                if field == 'uuid':
-                    return dev_uuid
-
-                devid = int(parts[1])
-                value = dom.get_device_property(klass, devid, field)
-                return value
+            for dom in self.domains.values():
+                if dom.has_device(klass, dev_uuid):
+                    return dom
+            return None
+        finally:
+            self.domains_lock.release()
+
+    def get_dev_property_by_uuid(self, klass, dev_uuid, field):
+        self.domains_lock.acquire()
+        try:
+            dom = self.get_vm_with_dev_uuid(klass, dev_uuid)
+            if not dom:
+                return None
+
+            value = dom.get_device_property(klass, devid, field)
+            return value
         except ValueError, e:
             pass
         
@@ -588,18 +591,7 @@ class XendDomain:
         return (self.get_vm_by_uuid(vm_ref) != None)
 
     def is_valid_dev(self, klass, dev_uuid):
-        parts = dev_uuid.split('-%s-' % klass, 1)
-        try:
-            if len(parts) > 1:
-                dom = self.get_vm_by_uuid(parts[0])
-                if not dom:
-                    return False
-                devid = int(parts[1])
-                return dom.isDeviceValid(klass, devid)
-        except ValueError, e:
-            pass
-            
-        return False
+        return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None)
 
     def do_legacy_api_with_uuid(self, fn, vm_uuid, *args):
         self.domains_lock.acquire()
index e4902324e1639efb423c484b0f797a0823941341..86c550247ff358a805090d8dd6867be7780d0749 100644 (file)
@@ -1709,54 +1709,73 @@ class XendDomainInfo:
             return XEN_API_ON_CRASH_BEHAVIOUR.index(self.info['on_crash'])
         except ValueError, e:
             return XEN_API_ON_CRASH_BEHAVIOUR.index('destroy')
-    
 
-    def get_device_property(self, devclass, devid, field):
-        controller =  self.getDeviceController(devclass)
-
-        if devclass == 'vif':
-            if field in ('name', 'MAC', 'type'):
-                config = controller.getDeviceConfiguration(devid)
-                if field == 'name':
-                    return config['vifname']
-                if field == 'mac':
-                    return config['mac']
-                if field == 'type':
-                    return config['type']
-            if field == 'device':
-                return 'eth%s' % devid
-            if field == 'network':
-                return None # TODO
-            if field == 'VM':
-                return self.get_uuid()
-            if field == 'MTU':
-                return 0 # TODO
-            # TODO: network bandwidth values
-            return 0.0
-
-        if devclass == 'vbd':
-            if field == 'VM':
-                return self.get_uuid()
-            if field == 'VDI':
-                return '' # TODO
-            if field in ('device', 'mode', 'driver'):
-                config = controller.getDeviceConfiguration(devid)
-                if field == 'device':
-                    return config['dev'] # TODO
-                if field == 'mode':
-                    return config['mode']
-                if field == 'driver':
-                    return config['uname'] # TODO
-
-            # TODO network bandwidth values
-            return 0.0
-
-        raise XendError("Unrecognised dev class or property")
-
-
-    def is_device_valid(self, devclass, devid):
-        controller = self.getDeviceController(devclass)
-        return (devid in controller.deviceIDs())
+    def get_dev_config_by_uuid(self, dev_class, dev_uuid):
+        """ Get's a device configuration either from XendConfig or
+        from the DevController."""
+        if self.get_power_state() not in ('Halted',):
+            dev = self.info['device'].get(dev_uuid)
+            if dev:
+                return dev[1].copy()
+            return None
+        else:
+            controller = self.getDeviceController(dev_class)
+            if not controller:
+                return None
+            all_configs = controller.getAllDeviceConfigurations()
+            if not all_configs:
+                return None
+            for _devid, _devcfg in all_configs.items():
+                if _devcfg.get('uuid') == dev_uuid:
+                    devcfg = _devcfg.copy()
+                    devcfg['id'] = _devid
+                    return devcfg
+
+        return None
+                    
+    def get_dev_xenapi_config(self, dev_class, dev_uuid):
+        config = self.get_dev_config_by_uuid(dev_class, dev_uuid)
+        if not config:
+            return {}
+        
+        config['VM'] = self.get_uuid()
+        
+        if dev_class == 'vif':
+            if not config.has_key('name'):
+                config['name'] = config.get('vifname', '')
+            if not config.has_key('MAC'):
+                config['MAC'] = config.get('mac', '')
+            if not config.has_key('type'):
+                config['type'] = 'paravirtualised'
+            if not config.has_key('device'):
+                devid = config.get('id')
+                if devid != None:
+                    config['device'] = 'eth%d' % devid
+                else:
+                    config['device'] = ''
+                    
+            config['network'] = '' # Invalid for Xend
+            config['MTU'] = 1500 # TODO
+            config['network_read_kbs'] = 0.0
+            config['network_write_kbs'] = 0.0
+            config['IO_bandwidth_incoming_kbs'] = 0.0
+            config['IO_bandwidth_outgoing_kbs'] = 0.0
+
+        if dev_class == 'vbd':
+            config['VDI'] = '' # TODO
+            config['device'] = config.get('dev', '')
+            config['driver'] = config.get('uname', '')
+            config['IO_bandwidth_incoming_kbs'] = 0.0
+            config['IO_bandwidth_outgoing_kbs'] = 0.0                        
+
+        return config
+
+    def get_dev_property(self, dev_class, dev_uuid, field):
+        config = self.get_dev_xenapi_config(dev_class, dev_uuid)
+        try:
+            return config[field]
+        except KeyError:
+            raise XendError('Invalid property for device: %s' % field)
 
     def get_vcpus_util(self):
         # TODO: this returns the total accum cpu time, rather than util
@@ -1806,7 +1825,9 @@ class XendDomainInfo:
             raise XendError("Device creation failed")
 
         return dev_uuid
-    
+
+    def has_device(self, dev_class, dev_uuid):
+        return (dev_uuid in self.info['%s_refs' % dev_class])
 
     """
         def stateChar(name):
index 16797312d4e256d01c14333a363d9d0b610416ed..1284c8b65dd832671c04479776204410d8193fcc 100644 (file)
@@ -256,6 +256,13 @@ class DevController:
 
         return {'backend': int(backdomid)}
 
+    def getAllDeviceConfigurations(self):
+        all_configs = {}
+        for devid in self.deviceIDs():
+            config_dict = self.getDeviceConfiguration(devid)
+            all_configs[devid] = config_dict
+        return all_configs
+
     ## protected:
 
     def getDeviceDetails(self, config):